﻿using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;

namespace Informant.UI
{
	public abstract class BindableObject : INotifyPropertyChanged
	{
		public event PropertyChangedEventHandler PropertyChanged;

		/// <summary>
		/// Fires a change notification for the specified property.
		/// </summary>
		/// <param name="propertyName">Name of the property.</param>
		protected virtual void PropertyChange(String propertyName)
		{
			if (String.IsNullOrEmpty(propertyName))
			{
				throw new ArgumentNullException("propertyName");
			}

			ValidatePropertyExists(propertyName);

			if (PropertyChanged != null)
			{
				PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
			}
		}

		/// <summary>
		/// Validates that the property to fire notifications for exists.
		/// </summary>
		/// <param name="propertyName">Name of the property.</param>
		/// <remarks>
		/// Executed only in debug builds
		/// </remarks>
		[Conditional("DEBUG")]
		protected void ValidatePropertyExists(String propertyName)
		{
			Type type = GetType();
			PropertyInfo info = type.GetProperty(propertyName);

			if (info == null)
			{
				String message = String.Format(CultureInfo.CurrentCulture, "{0} is not a public property of {1}", propertyName, type.FullName);
				throw new ArgumentOutOfRangeException(propertyName, message);
			}
		}
	}
}
